<html lang="en"><head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Drawing App</title>
  <!-- Tailwind CSS v3 -->
  <script src="https://cdn.tailwindcss.com"></script>
  <!-- Font Awesome -->
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  
  <!-- Tailwind 配置 -->
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3B82F6',
            secondary: '#10B981',
            accent: '#F59E0B',
            dark: '#1F2937',
            light: '#F9FAFB'
          },
          fontFamily: {
            inter: ['Inter', 'sans-serif'],
          },
        },
      }
    }
  </script>
  
  <!-- 自定义工具类 -->
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .canvas-shadow {
        box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
      }
      .control-panel {
        backdrop-filter: blur(8px);
        background-color: rgba(255, 255, 255, 0.8);
      }
      .transparent-bg {
        background-image: linear-gradient(45deg, #eee 25%, transparent 25%),
                          linear-gradient(-45deg, #eee 25%, transparent 25%),
                          linear-gradient(45deg, transparent 75%, #eee 75%),
                          linear-gradient(-45deg, transparent 75%, #eee 75%);
        background-size: 20px 20px;
        background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
      }
    }
  </style>
  
  <!-- 导入字体 -->
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&amp;display=swap" rel="stylesheet">
</head>
<body class="bg-gradient-to-br from-gray-100 to-gray-200 min-h-screen font-inter text-dark">
  <div class="container mx-auto px-4 py-8 max-w-6xl">
    <!-- 标题 -->
    <header class="text-center mb-8">
      <h1 class="text-[clamp(2rem,5vw,3rem)] font-bold text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary mb-2">Canvas Drawing</h1>
      <p class="text-gray-600 max-w-2xl mx-auto">Create beautiful drawings with our powerful canvas-based drawing tool. Choose colors, adjust brush size, and let your creativity flow.</p>
    </header>
    
    <!-- 画布容器 -->
    <div class="relative mb-6">
      <canvas id="drawingCanvas" class="w-full h-[60vh] md:h-[70vh] bg-white rounded-xl canvas-shadow cursor-crosshair"></canvas>
      
      <!-- 浮动控制面板 -->
      <div class="control-panel absolute top-4 left-4 p-3 rounded-lg shadow-lg flex flex-col gap-3 z-10">
        <div class="flex flex-col gap-2">
          <label class="text-sm font-medium text-gray-700">Brush Size</label>
          <input type="range" id="brushSize" min="1" max="50" value="5" class="w-48 accent-primary">
          <div class="flex justify-between text-xs text-gray-500">
            <span>Small</span>
            <span>Large</span>
          </div>
        </div>
        
        <div>
          <label class="text-sm font-medium text-gray-700 block mb-1">Colors</label>
          <div class="flex flex-wrap gap-2">
            <button class="w-6 h-6 rounded-full bg-black color-btn active" data-color="#000000"></button>
            <button class="w-6 h-6 rounded-full bg-red-500 color-btn" data-color="#EF4444"></button>
            <button class="w-6 h-6 rounded-full bg-blue-500 color-btn" data-color="#3B82F6"></button>
            <button class="w-6 h-6 rounded-full bg-green-500 color-btn" data-color="#22C55E"></button>
            <button class="w-6 h-6 rounded-full bg-yellow-500 color-btn" data-color="rgba(235, 39, 170, .36)"></button>
            <button class="w-6 h-6 rounded-full bg-purple-500 color-btn" data-color="#A855F7"></button>
            <button class="w-6 h-6 rounded-full bg-pink-500 color-btn" data-color="#EC4899"></button>
            <button class="w-6 h-6 rounded-full bg-gray-300 color-btn" data-color="#D1D5DB"></button>
            <button class="w-6 h-6 rounded-full bg-white border border-gray-300 color-btn" data-color="#FFFFFF"></button>
            
            <!-- 透明色选项 -->
            <button class="w-6 h-6 rounded-full transparent-bg border border-gray-300 color-btn" data-color="rgba(0,0,0,0.7)"></button>
            <button class="w-6 h-6 rounded-full transparent-bg border border-gray-300 color-btn" data-color="rgba(0,0,0,0.5)"></button>
            <button class="w-6 h-6 rounded-full transparent-bg border border-gray-300 color-btn" data-color="rgba(0,0,0,0.3)"></button>
          </div>
        </div>
      </div>
      
      <!-- 操作按钮 -->
      <div class="absolute bottom-4 right-4 flex gap-3">
        <button id="undoBtn" class="p-3 bg-white rounded-full shadow-md hover:bg-gray-50 transition-colors">
          <i class="fa fa-undo text-gray-600"></i>
        </button>
        <button id="redoBtn" class="p-3 bg-white rounded-full shadow-md hover:bg-gray-50 transition-colors">
          <i class="fa fa-repeat text-gray-600"></i>
        </button>
        <button id="clearBtn" class="p-3 bg-white rounded-full shadow-md hover:bg-gray-50 transition-colors">
          <i class="fa fa-trash text-gray-600"></i>
        </button>
      </div>
    </div>
    
    <!-- 信息面板 -->
    <div class="bg-white p-4 rounded-lg shadow-sm">
      <div class="flex flex-wrap justify-between items-center gap-4">
        <div>
          <span class="text-sm font-medium text-gray-500">Current Color:</span>
          <span id="currentColorDisplay" class="inline-block w-4 h-4 rounded-full bg-black ml-2"></span>
          <span class="text-sm font-medium text-gray-500 ml-4">Brush Size:</span>
          <span id="currentSizeDisplay" class="text-sm font-medium">5px</span>
        </div>
        <div class="text-sm text-gray-500">
          <i class="fa fa-info-circle mr-1"></i>
          Use your mouse or touch to draw. Undo with Ctrl+Z (Cmd+Z) and redo with Ctrl+Y (Cmd+Y).
        </div>
      </div>
    </div>
  </div>
  
  <footer class="mt-12 py-6 text-center text-gray-500 text-sm">
    <p>Created with <i class="fa fa-heart text-red-500"></i> using HTML5 Canvas and JavaScript</p>
  </footer>

  <script>
    // 获取DOM元素
    const canvas = document.getElementById('drawingCanvas');
    const ctx = canvas.getContext('2d');
    const brushSize = document.getElementById('brushSize');
    const colorBtns = document.querySelectorAll('.color-btn');
    const currentColorDisplay = document.getElementById('currentColorDisplay');
    const currentSizeDisplay = document.getElementById('currentSizeDisplay');
    const undoBtn = document.getElementById('undoBtn');
    const redoBtn = document.getElementById('redoBtn');
    const clearBtn = document.getElementById('clearBtn');
    
    // 设置画布尺寸
    function resizeCanvas() {
      const container = canvas.parentElement;
      canvas.width = container.clientWidth;
      canvas.height = container.clientHeight;
    }
    
    // 初始化画布
    function initCanvas() {
      resizeCanvas();
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      ctx.strokeStyle = '#000000';
      ctx.lineWidth = 5;
      
      // 存储绘制历史
      drawingHistory = [];
      currentStep = -1;
      
      // 保存初始状态
      saveDrawingState();
    }
    
    // 存储绘制历史
    let drawingHistory = [];
    let currentStep = -1;
    
    // 保存当前画布状态
    function saveDrawingState() {
      // 如果当前步骤不是最新的，删除后面的所有状态
      if (currentStep < drawingHistory.length - 1) {
        drawingHistory = drawingHistory.slice(0, currentStep + 1);
      }
      
      // 保存当前画布状态
      drawingHistory.push(canvas.toDataURL());
      currentStep++;
      
      // 更新按钮状态
      updateButtonState();
    }
    
    // 更新按钮状态
    function updateButtonState() {
      undoBtn.disabled = currentStep <= 0;
      redoBtn.disabled = currentStep >= drawingHistory.length - 1;
      
      undoBtn.classList.toggle('opacity-50', currentStep <= 0);
      redoBtn.classList.toggle('opacity-50', currentStep >= drawingHistory.length - 1);
    }
    
    // 撤销操作
    function undo() {
      if (currentStep > 0) {
        currentStep--;
        const img = new Image();
        img.src = drawingHistory[currentStep];
        img.onload = function() {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.drawImage(img, 0, 0);
        };
        updateButtonState();
      }
    }
    
    // 重做操作
    function redo() {
      if (currentStep < drawingHistory.length - 1) {
        currentStep++;
        const img = new Image();
        img.src = drawingHistory[currentStep];
        img.onload = function() {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.drawImage(img, 0, 0);
        };
        updateButtonState();
      }
    }
    
    // 清除画布
    function clearCanvas() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      saveDrawingState();
    }
    
    // 绘制逻辑
    let isDrawing = false;
    let lastX = 0;
    let lastY = 0;
    
    function startDrawing(e) {
      isDrawing = true;
      [lastX, lastY] = getCanvasCoordinates(e);
    }
    
    function draw(e) {
      if (!isDrawing) return;
      
      ctx.beginPath();
      ctx.moveTo(lastX, lastY);
      
      const [x, y] = getCanvasCoordinates(e);
      ctx.lineTo(x, y);
      ctx.stroke();
      
      [lastX, lastY] = [x, y];
    }
    
    function stopDrawing() {
      if (isDrawing) {
        isDrawing = false;
        saveDrawingState();
      }
    }
    
    // 获取鼠标/触摸在画布上的坐标
    function getCanvasCoordinates(e) {
      const rect = canvas.getBoundingClientRect();
      
      if (e.type.startsWith('touch')) {
        const touch = e.touches[0] || e.changedTouches[0];
        return [
          touch.clientX - rect.left,
          touch.clientY - rect.top
        ];
      } else {
        return [
          e.clientX - rect.left,
          e.clientY - rect.top
        ];
      }
    }
    
    // 事件监听
    window.addEventListener('resize', resizeCanvas);
    
    // 鼠标事件
    canvas.addEventListener('mousedown', startDrawing);
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', stopDrawing);
    canvas.addEventListener('mouseout', stopDrawing);
    
    // 触摸事件
    canvas.addEventListener('touchstart', startDrawing, { passive: true });
    canvas.addEventListener('touchmove', draw, { passive: true });
    canvas.addEventListener('touchend', stopDrawing);
    canvas.addEventListener('touchcancel', stopDrawing);
    
    // 笔刷大小调整
    brushSize.addEventListener('input', function() {
      ctx.lineWidth = this.value;
      currentSizeDisplay.textContent = `${this.value}px`;
    });
    
    // 颜色选择
    colorBtns.forEach(btn => {
      btn.addEventListener('click', function() {
        // 移除所有活动状态
        colorBtns.forEach(b => b.classList.remove('ring-2', 'ring-primary', 'ring-offset-2'));
        
        // 添加活动状态
        this.classList.add('ring-2', 'ring-primary', 'ring-offset-2');
        
        // 设置画笔颜色
        const color = this.getAttribute('data-color');
        ctx.strokeStyle = color;
        
        // 更新当前颜色显示
        if (color.startsWith('rgba')) {
          // 对于透明色，使用背景图显示
          currentColorDisplay.className = 'inline-block w-4 h-4 rounded-full transparent-bg border border-gray-300 ml-2';
        } else {
          // 对于实色，直接设置背景色
          currentColorDisplay.className = 'inline-block w-4 h-4 rounded-full ml-2';
          currentColorDisplay.style.backgroundColor = color;
        }
      });
    });
    
    // 按钮事件
    undoBtn.addEventListener('click', undo);
    redoBtn.addEventListener('click', redo);
    clearBtn.addEventListener('click', clearCanvas);
    
    // 键盘快捷键
    document.addEventListener('keydown', function(e) {
      // Ctrl+Z 或 Cmd+Z 撤销
      if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
        e.preventDefault();
        undo();
      }
      
      // Ctrl+Y 或 Cmd+Y 重做
      if ((e.ctrlKey || e.metaKey) && e.key === 'y') {
        e.preventDefault();
        redo();
      }
      
      // Ctrl+Backspace 清除画布
      if ((e.ctrlKey || e.metaKey) && e.key === 'Backspace') {
        e.preventDefault();
        clearCanvas();
      }
    });
    
    // 初始化应用
    initCanvas();
  </script>


</body></html>